package com.ssl.product.pojo;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.NestedQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.nested.NestedAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;

import java.util.List;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ProductSearchBody {
    private String key; //skuTitle

    private Long categoryId;
    private List<Long> brandIds;
    private Long[] price;

    private String sort; // 内部进行自定义。 price_asc
    private Integer pageNum; //es的单次查询最高限额是 10000条 + 自己定义的一个单页的最多的数据

    private List<String> attrs; //9:35,36. 校长，我既选择9属性的 35，又选择10属性的白色，这是同时传输的2种筛选方式，你一个string怎么搞？

    public SearchRequest generateSearchRequest() {
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        /**
         * query part start
         */
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        if(StringUtils.isNotEmpty(key)) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("skuTitle", key));
        }

        if(categoryId != null) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("categoryId", categoryId));
        }
        if (brandIds != null && brandIds.size() > 0) {
            boolQueryBuilder.filter(QueryBuilders.termsQuery("brandId", brandIds));
        }
        if(price != null) {
            RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("price");
            rangeQueryBuilder.gte(price[0]).lte(price[1]);
            boolQueryBuilder.filter(rangeQueryBuilder);
        }

        BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
        if(attrs != null && attrs.size() > 0) {
            attrs.stream().forEach(attr -> {
                String[] attrSplit = attr.split(":");
                queryBuilder.must(QueryBuilders.termQuery("attrs.attrId", attrSplit[0]));
                String[] multiAttrValues = attrSplit[1].split(",");
                queryBuilder.must(QueryBuilders.termsQuery("attrs.attrValue", multiAttrValues));
            });
        }
        NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery("attrs", queryBuilder, ScoreMode.None);
        boolQueryBuilder.filter(nestedQueryBuilder);
        sourceBuilder.query(boolQueryBuilder);
        /**
         * query part end
         */

        /**
         * sort start
         */
        if(StringUtils.isNotEmpty(sort)) {
            String[] sortSplits = sort.split("_");
            sourceBuilder.sort(sortSplits[0], sortSplits[1].equalsIgnoreCase("asc") ? SortOrder.ASC : SortOrder.DESC);
        }
        sourceBuilder.from((pageNum - 1) * 50);
        sourceBuilder.size(50);
        /**
         * sort end
         */

        /**
         * agg start
         */
        TermsAggregationBuilder brandAgg = AggregationBuilders.terms("brandAgg").field("brandId").size(50);
        TermsAggregationBuilder brandNameAgg = AggregationBuilders.terms("brandNameAgg").field("brandName").size(50);
        brandAgg.subAggregation(brandNameAgg);
        sourceBuilder.aggregation(brandAgg);

        NestedAggregationBuilder nestedAggregationBuilder = new NestedAggregationBuilder("attrs", "attrs");
        TermsAggregationBuilder attrIdAgg = AggregationBuilders.terms("attrIdAgg").field("attrs.attrId").size(50);
        TermsAggregationBuilder attrNameAgg = AggregationBuilders.terms("attrNameAgg").field("attrs.attrName").size(50);
        TermsAggregationBuilder attrValueAgg = AggregationBuilders.terms("attrValueAgg").field("attrs.attrValue").size(50);
        attrIdAgg.subAggregation(attrNameAgg);
        attrIdAgg.subAggregation(attrValueAgg);
        nestedAggregationBuilder.subAggregation(attrIdAgg);
        sourceBuilder.aggregation(nestedAggregationBuilder);
        /**
         * agg end
         */

        return new SearchRequest(new String[] {"commodity"}, sourceBuilder);
    }
}
